import {
  PromptTemplate,
  PromptSection,
  PromptSectionType,
  PromptBuildContext,
  PromptCondition,
  PromptVariable,
  ChatMode,
  EnhancedPromptConfig
} from './types';
import * as Handlebars from 'handlebars';

/**
 * 提示词模板引擎
 * 负责管理和渲染提示词模板
 */
export class PromptTemplateEngine {
  private templates = new Map<string, PromptTemplate>();
  private defaultTemplates = new Map<ChatMode, string>();

  constructor() {
    this.initializeDefaultTemplates();
  }

  /**
   * 注册提示词模板
   */
  registerTemplate(template: PromptTemplate): void {
    this.templates.set(template.id, template);
  }

  /**
   * 获取提示词模板
   */
  getTemplate(id: string): PromptTemplate | undefined {
    return this.templates.get(id);
  }

  /**
   * 设置默认模板
   */
  setDefaultTemplate(mode: ChatMode, templateId: string): void {
    this.defaultTemplates.set(mode, templateId);
  }

  /**
   * 获取默认模板
   */
  getDefaultTemplate(mode: ChatMode): PromptTemplate | undefined {
    const templateId = this.defaultTemplates.get(mode);
    return templateId ? this.getTemplate(templateId) : undefined;
  }

  /**
   * 构建提示词
   */
  buildPrompt(
    context: PromptBuildContext,
    config?: EnhancedPromptConfig
  ): string {
    // 选择模板
    const template = this.selectTemplate(context, config);
    if (!template) {
      throw new Error(`No template found for mode: ${context.mode}`);
    }

    // 验证变量
    this.validateVariables(template, context.variables || {});

    // 渲染模板
    return this.renderTemplate(template, context, config);
  }

  /**
   * 选择合适的模板
   */
  private selectTemplate(
    context: PromptBuildContext,
    config?: EnhancedPromptConfig
  ): PromptTemplate | undefined {
    // 优先使用配置指定的模板
    if (config?.templateId) {
      const template = this.getTemplate(config.templateId);
      if (template && template.mode === context.mode) {
        return template;
      }
    }

    // 使用默认模板
    return this.getDefaultTemplate(context.mode);
  }

  /**
   * 验证模板变量
   */
  private validateVariables(
    template: PromptTemplate,
    variables: Record<string, any>
  ): void {
    if (!template.variables) return;

    for (const [name, varDef] of Object.entries(template.variables)) {
      const value = variables[name];
      // 检查必需变量
      if (varDef.required && (value === undefined || value === null)) {
        throw new Error(`Required variable '${name}' is missing`);
      }

      // 类型检查
      if (value !== undefined && !this.validateVariableType(value, varDef)) {
        throw new Error(`Variable '${name}' has invalid type`);
      }

      // 验证规则检查
      if (value !== undefined && varDef.validation) {
        this.validateVariableValue(name, value, varDef.validation);
      }
    }
  }

  /**
   * 验证变量类型
   */
  private validateVariableType(value: any, varDef: PromptVariable): boolean {
    const actualType = Array.isArray(value) ? 'array' : typeof value;
    return actualType === varDef.type;
  }

  /**
   * 验证变量值
   */
  private validateVariableValue(
    name: string,
    value: any,
    validation: any
  ): void {
    if (validation.minLength && value.length < validation.minLength) {
      throw new Error(`Variable '${name}' is too short`);
    }

    if (validation.maxLength && value.length > validation.maxLength) {
      throw new Error(`Variable '${name}' is too long`);
    }

    if (validation.pattern && !new RegExp(validation.pattern).test(value)) {
      throw new Error(`Variable '${name}' does not match pattern`);
    }

    if (validation.enum && !validation.enum.includes(value)) {
      throw new Error(`Variable '${name}' is not in allowed values`);
    }
  }

  /**
   * 渲染模板
   */
  private renderTemplate(
    template: PromptTemplate,
    context: PromptBuildContext,
    config?: EnhancedPromptConfig
  ): string {
    const sections: string[] = [];

    // 渲染系统提示词
    if (template.systemPrompt) {
      const systemPrompt = this.renderString(template.systemPrompt, context);
      sections.push(systemPrompt);
    }

    // 渲染各个段落
    const enabledSections = this.getEnabledSections(template.sections, context);
    const sortedSections = this.sortSectionsByPriority(enabledSections);

    for (const section of sortedSections) {
      const renderedSection = this.renderSection(section, context, config);
      if (renderedSection) {
        sections.push(renderedSection);
      }
    }

    return sections.join('\n\n');
  }

  /**
   * 获取启用的段落
   */
  private getEnabledSections(
    sections: PromptSection[],
    context: PromptBuildContext
  ): PromptSection[] {
    return sections.filter(section => {
      if (!section.enabled) return false;

      // 检查条件
      if (section.conditions) {
        return section.conditions.every(condition =>
          this.evaluateCondition(condition, context)
        );
      }

      return true;
    });
  }

  /**
   * 按优先级排序段落
   */
  private sortSectionsByPriority(sections: PromptSection[]): PromptSection[] {
    return [...sections].sort((a, b) => (b.priority || 0) - (a.priority || 0));
  }

  /**
   * 渲染段落
   */
  private renderSection(
    section: PromptSection,
    context: PromptBuildContext,
    config?: EnhancedPromptConfig
  ): string | null {
    let content = this.renderString(section.template, context);

    // 应用长度限制
    if (section.maxLength && content.length > section.maxLength) {
      content = this.truncateContent(content, section.maxLength);
    }

    return content || null;
  }

  /**
   * 渲染字符串模板
   */
  private renderString(template: string, context: PromptBuildContext): string {
    try {
      // Compile the Handlebars template
      const compiledTemplate = Handlebars.compile(template);

      // Create the data object for Handlebars
      const templateData = {
        ...context.variables,
        mode: context.mode,
        userMessage: context.userMessage,
        conversationHistory: context.conversationHistory,
        codeContext: context.codeContext,
        memories: context.memories,
        toolHistory: context.toolHistory,
        guidelines: context.guidelines,
        rules: context.rules,
        metadata: context.metadata
      };

      // Render the template
      return compiledTemplate(templateData);
    } catch (error) {
      console.warn('Failed to render Handlebars template:', error);
      // Fallback to simple variable replacement
      return template.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (match, path) => {
        const value = this.getValueByPath(context, path);
        return value !== undefined ? String(value) : match;
      });
    }
  }

  /**
   * 通过路径获取值
   */
  private getValueByPath(obj: any, path: string): any {
    return path.split('.').reduce((current, key) => {
      return current && current[key] !== undefined ? current[key] : undefined;
    }, obj);
  }

  /**
   * 评估条件
   */
  private evaluateCondition(
    condition: PromptCondition,
    context: PromptBuildContext
  ): boolean {
    if (condition.customCheck) {
      return condition.customCheck(context);
    }

    const value = this.getValueByPath(context, condition.field);

    switch (condition.operator) {
      case 'exists':
        return value !== undefined && value !== null;
      case 'eq':
        return value === condition.value;
      case 'ne':
        return value !== condition.value;
      case 'gt':
        return value > condition.value;
      case 'lt':
        return value < condition.value;
      case 'contains':
        return Array.isArray(value)
          ? value.includes(condition.value)
          : String(value).includes(String(condition.value));
      default:
        return false;
    }
  }

  /**
   * 截断内容
   */
  private truncateContent(content: string, maxLength: number): string {
    if (content.length <= maxLength) return content;

    const truncated = content.substring(0, maxLength - 3);
    const lastSpace = truncated.lastIndexOf(' ');

    return lastSpace > maxLength * 0.8
      ? truncated.substring(0, lastSpace) + '...'
      : truncated + '...';
  }

  /**
   * 初始化默认模板
   */
  private initializeDefaultTemplates(): void {
    // 这里会在后续实现中添加默认模板
  }
}
